package br.urca.controller;

import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.List;
import java.util.TimeZone;

import javax.annotation.PostConstruct;
import javax.inject.Inject;
import javax.servlet.ServletContext;
import javax.transaction.Transactional;

import br.com.caelum.vraptor.Controller;
import br.com.caelum.vraptor.Get;
import br.com.caelum.vraptor.Path;
import br.com.caelum.vraptor.Result;
import br.com.caelum.vraptor.controller.IndexController;
import br.com.caelum.vraptor.jasperreports.Report;
import br.com.caelum.vraptor.jasperreports.download.ReportDownload;
import br.com.caelum.vraptor.jasperreports.formats.ExportFormats;
import br.com.caelum.vraptor.observer.download.Download;
import br.urca.dao.AlunosCursoDAO;
import br.urca.dao.AproveitamentoDAO;
import br.urca.dao.AtividadeAlunoDAO;
import br.urca.dao.CursoTurnoDAO;
import br.urca.dao.DisciplinaDAO;
import br.urca.dao.DisciplinasCursadasDAO;
import br.urca.dao.DisciplinasMatriculadasDAO;
import br.urca.dao.DocumentoEmitidoDAO;
import br.urca.dao.EquivalenciaDAO;
import br.urca.dao.GradeCursoDAO;
import br.urca.dao.HabilitacaoDAO;
import br.urca.dao.HistoricoDAO;
import br.urca.dao.OfertaDAO;
import br.urca.dao.PeriodoDAO;
import br.urca.dao.SituacaoDisciplinaDAO;
import br.urca.helper.HistoricoAluno;
import br.urca.http.ProtocoloSolicitacaoHTTP;
import br.urca.interceptor.InterceptResource;
import br.urca.model.CursoTurno;
import br.urca.model.DocumentoEmitido;
import br.urca.model.DocumentoEmitidoPK;
import br.urca.model.Periodo;
import br.urca.model.json.ProtocoloSolicitacao;
import br.urca.model.relatorio.ComprovanteSoliColGrau;
import br.urca.report.AbstractReport;
import br.urca.session.UsuarioLogado;
import br.urca.util.AutenticacaoDocumento;
import br.urca.util.ETipoDocumento;
import br.urca.util.Paths;

@InterceptResource
@Controller
public class SolicitacoesController {
	
	private DisciplinasCursadasDAO mCursadasDAO;
	private DisciplinasMatriculadasDAO mMatriculadasDAO;
	private DisciplinaDAO mDisciplinaDAO;
	private OfertaDAO mOfertaDAO;
	private AlunosCursoDAO mCursoDAO;
	private GradeCursoDAO mGradeCursoDAO;
	private AtividadeAlunoDAO mAtividadeAlunoDAO;
	private HistoricoDAO mHistoricoDAO;
	private AproveitamentoDAO mAproveitamentoDAO;
	private HabilitacaoDAO mHabilitacaoDAO;
	private EquivalenciaDAO mEquivalenciaDAO;
	private SituacaoDisciplinaDAO mSituacaoDisciplinaDAO;
	private UsuarioLogado usuarioLogado;
	private PeriodoDAO mPeriodoDAO;
	private CursoTurnoDAO mCursoTurnoDAO;
	private ServletContext context;
	private Result result;
	private DocumentoEmitidoDAO mEmitidosDAO;
	
	@Deprecated public SolicitacoesController() { }
	
	@Inject
	public SolicitacoesController(DisciplinasCursadasDAO mCursadasDAO,
			DisciplinasMatriculadasDAO mMatriculadasDAO,
			DisciplinaDAO mDisciplinaDAO, OfertaDAO mOfertaDAO,
			AlunosCursoDAO mCursoDAO, GradeCursoDAO mGradeCursoDAO,
			AtividadeAlunoDAO mAtividadeAlunoDAO, HistoricoDAO mHistoricoDAO,
			AproveitamentoDAO mAproveitamentoDAO, CursoTurnoDAO mCursoTurnoDAO,
			HabilitacaoDAO mHabilitacaoDAO, EquivalenciaDAO mEquivalenciaDAO,
			SituacaoDisciplinaDAO mSituacaoDisciplinaDAO,
			UsuarioLogado usuarioLogado, PeriodoDAO mPeriodoDAO,
			ServletContext context, Result result,
			DocumentoEmitidoDAO mEmitidosDAO) {
		this.mCursadasDAO = mCursadasDAO;
		this.mMatriculadasDAO = mMatriculadasDAO;
		this.mDisciplinaDAO = mDisciplinaDAO;
		this.mOfertaDAO = mOfertaDAO;
		this.mCursoDAO = mCursoDAO;
		this.mGradeCursoDAO = mGradeCursoDAO;
		this.mAtividadeAlunoDAO = mAtividadeAlunoDAO;
		this.mHistoricoDAO = mHistoricoDAO;
		this.mAproveitamentoDAO = mAproveitamentoDAO;
		this.mHabilitacaoDAO = mHabilitacaoDAO;
		this.mEquivalenciaDAO = mEquivalenciaDAO;
		this.mSituacaoDisciplinaDAO = mSituacaoDisciplinaDAO;
		this.usuarioLogado = usuarioLogado;
		this.mPeriodoDAO = mPeriodoDAO;
		this.context = context;
		this.result = result;
		this.mEmitidosDAO = mEmitidosDAO;
		this.mCursoTurnoDAO = mCursoTurnoDAO;
	}
	
	@Path("/solicitacoes")
	public void index() {
		//verificarRequerimento();		
	}
	
	public void verificarPossivelConcludente() {
		
		HistoricoAluno mHistoricoAluno = new HistoricoAluno(
				mCursadasDAO, mMatriculadasDAO, mHabilitacaoDAO,
				usuarioLogado, mHistoricoDAO, mAtividadeAlunoDAO,
				mGradeCursoDAO, mDisciplinaDAO, mOfertaDAO,
				mSituacaoDisciplinaDAO, mCursoDAO, mAproveitamentoDAO,
				mEquivalenciaDAO, mEmitidosDAO, false);
		String curso = usuarioLogado.getAluno().getCodCursoTurno().trim();

		CursoTurno cursoTurno = mCursoTurnoDAO.buscarPorCursoTurno(usuarioLogado.getAluno().getCodCursoTurno(),
				usuarioLogado.getAluno().getCurso());
		if (cursoTurno.getColacaoGrauAtivo().equals(new Character('N'))) {
			result.include(
					"mensagem",
					"No momento a solicitação de colação de grau não está disponível para o seu curso. ");
		} else {
			if (!mHistoricoAluno.isEligibleGraduation()) {
				if (!result.included().containsKey("protocolo")) {
					result.include(
							"mensagem",
							"Infelizmente você não pode solicitar a colação de grau, "
							+ "pois a quantidade de créditos ainda não é suficiente para conclusão do curso.");
				}
			} 
		}
	}
	
	@PostConstruct
	public void verificarRequerimento() {
		Periodo periodo = mPeriodoDAO.getPeriodoPadrao();
		ProtocoloSolicitacao protocolo = ProtocoloSolicitacaoHTTP
				.consultarRequerimentoColacao(Paths.KEY_APPLICATION, periodo
						.getPeriodoLetivo(), usuarioLogado.getAluno()
						.getMatricula());
		if (!usuarioLogado.getAluno().getSituacao().getId().equalsIgnoreCase(AlunosCursoController.SITUACAO_REGULAR)) {
			this.result.include("mensagem",
					"Não é possível fazer a solicitação da colação de grau. Pois sua situação é: "
							+ usuarioLogado.getAluno().getSituacao()
									.getDescricao()+".");
		} else {
			if (protocolo != null)
				this.result.include("protocolo", protocolo);
		}	
		verificarPossivelConcludente();
	}
	
	public void solicitarColacao() {
		if (usuarioLogado.getAluno().getSituacao().getId().equalsIgnoreCase(AlunosCursoController.SITUACAO_REGULAR)) {
			Periodo periodo = mPeriodoDAO.getPeriodoPadrao();
			ProtocoloSolicitacaoHTTP
					.solicitarColacao(Paths.KEY_APPLICATION, periodo
							.getPeriodoLetivo(), usuarioLogado.getAluno()
							.getMatricula());
			this.result.redirectTo(this).index();
			
			//Opção para desabilitar a solicitação de colação de grau.
			/*this.result
					.include("mensagem",
							"Ainda não estamos no período de solicitação de colação de grau.")
					.redirectTo(this).index();*/			
		}	
	}
	
	@Get("/solicitacao/comprovante/colacao/pdf")
	@Transactional
	public Download comprovanteSCG() {
		try {
			Periodo periodo = mPeriodoDAO.getPeriodoPadrao();
			if (periodo != null) {
				ProtocoloSolicitacao protocolo = ProtocoloSolicitacaoHTTP
						.consultarRequerimentoColacao(Paths.KEY_APPLICATION, periodo
								.getPeriodoLetivo(), usuarioLogado.getAluno()
								.getMatricula());
				if (protocolo != null) {
					
					List<ComprovanteSoliColGrau> mList = new ArrayList<ComprovanteSoliColGrau>();
					ComprovanteSoliColGrau cscg = new ComprovanteSoliColGrau();
					
					cscg.setAluno(usuarioLogado.getAluno().getAluno().getNome());
					cscg.setData(protocolo.getData());
					cscg.setPeriodo(protocolo.getPeriodo());
					cscg.setProtocolo(protocolo.getNumero());
					
					mList.add(cscg);
					
					AutenticacaoDocumento mAutenticacao = new AutenticacaoDocumento(usuarioLogado.getAluno().getMatricula(), ETipoDocumento.COMPROVANTE_SOLI_COL_GRAU);
					
					Report report = new AbstractReport(mList, "comp_soli_colacao.jasper", "comp_soli_colacao_");
					String realPath = context.getRealPath("/WEB-INF/reports/images/");	
					report.addParameter("realPath", realPath);
					report.addParameter("md5", mAutenticacao.getAutenticacao());
			        report.addParameter("validacao", mAutenticacao.getHash());
			        report.addParameter("validade", getValidade());
			        
			        if (salvarEmissaoDeDeclaracao(usuarioLogado.getAluno().getMatricula(), mAutenticacao.getHash(), 
			        		(short) ETipoDocumento.COMPROVANTE_SOLI_COL_GRAU.getTipo())) {
			        	return new ReportDownload(report, ExportFormats.pdf(), false);
			        } else {
			        	throw new Exception("Falha ao tentar salvar o relatório!");
			        }
					
				} else {
					this.result
					.include("erro",
							"Comprovante não pode ser gerado, pois não há nenhum protocolo aberto.")
					.redirectTo(this).index();
				}
			} else {
				this.result
				.include("erro",
						"Não foi possível obter o período padrão. Por favor entre em contato com o D.T.I. URCA.")
				.redirectTo(this).index();
			}
		} catch(Exception e) {
			result.include(
					"erro",
					"Desculpe! Ocorreu algum problema e o comprovante não pôde ser emitido! Tente novamente em alguns minutos."+e.getMessage())
					.redirectTo(IndexController.class).index();
		}
		return null;		
	}
	
	public String getValidade() {
		SimpleDateFormat sdf = new SimpleDateFormat("dd/MM/yyyy");
		Calendar calendar = Calendar.getInstance(TimeZone.getDefault());
		calendar.add(Calendar.DAY_OF_MONTH, 90);
		return "Comprovante válido até "+sdf.format(calendar.getTime());
	}
	
	public boolean salvarEmissaoDeDeclaracao(String matricula, String md5, short tipoDocumento) {
		try {
			Calendar calendar = Calendar.getInstance(TimeZone.getDefault());
			DocumentoEmitido doc = new DocumentoEmitido();
	        doc.setId(new DocumentoEmitidoPK(matricula, 
	        		tipoDocumento,
	        		calendar.getTime()));
	        doc.setMd5(md5);
	        calendar.add(Calendar.DAY_OF_MONTH, 90);
	        doc.setValidade(calendar.getTime());
	        
	        mEmitidosDAO.salvar(doc);
	        return true;
		} catch(Exception e) {
			return false;
		}
	}

}
